home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
TCL1
/
CTRACE2_
/
CLOGPANO.C
< prev
next >
Wrap
Text File
|
1990-12-10
|
6KB
|
179 lines
/*****
from CTRACE: A MESSAGE LOGGING CLASS
by William D. Cramer in Dr. Dobbs Journal #170, p. 44-55, 116-120.
*****/
/** CLogPanorama.c -- Methods for a CLogPanorama class object. **/
#include "CLogPanorama.h" /* defines log class */
/** ILogPanorama -- Initializes an instance of the log panorama class. **/
void CLogPanorama::ILogPane
(
short records, /* number of records in LogList */
CBureaucrat *aSupervisor, /* in-charge for this panorama */
CWindow *aWindow /* window object to place pane into */
)
{
FontInfo
fontParms; /* paramaters of selected font */
short
lineSpace, /* pixels per line */
charSpace; /* pixels per widest character */
Rect
maxWindowRect, /* maximum growth of log window */
marginRect; /* inside margins of viewable area */
CScrollPane
*theScrollPane; /* pane associated with panorama */
/* Set drawing parameters and adjust record size, if necessary. **/
aWindow->Prepare ();
TextFont (LOGPANE_FONT);
TextSize (LOGPANE_FONT_SIZE);
GetFontInfo (&fontParms);
lineSpace = fontParms.ascent+fontParms.descent+fontParms.leading;
charSpace = fontParms.widMax;
if ( ((long)records*(long)lineSpace) > (long)INT_MAX)
records = INT_MAX / lineSpace;
SetRect (&maxWindowRect, MIN_WSIZE, MIN_WSIZE,
(MAX_LOGREC_CHAR * charSpace) + SBARSIZE,
(records * lineSpace) + SBARSIZE);
aWindow->SetSizeRect (&maxWindowRect);
/* Initialize Panorama's ScrollPane, set scroll units to the defaulted
** values, and attach the Panorama to the ScrollPane. */
theScrollPane = new (CScrollPane);
theScrollPane->IScrollPane(aWindow, this, 0, 0, 0, 0,sizELASTIC, sizELASTIC,TRUE, TRUE, TRUE);
theScrollPane->FitToEnclFrame (TRUE, TRUE);
theScrollPane->SetSteps (LOGPANE_HORZ_SCROLL, LOGPANE_VERT_SCROLL);
/* Initialize Panarama to include maximum chars wide and maximum records tall,
** set the Panarama units to one char wide and one char tall. */
CPanorama::IPanorama(theScrollPane, aSupervisor, MAX_LOGREC_CHAR,
records, 0, 0, sizELASTIC, sizELASTIC);
SetScales (charSpace, lineSpace);
FitToEnclosure (TRUE, TRUE);
theScrollPane->InstallPanorama (this);
/* Create the LogList and initialize. */
itsLogList = new (CLogList);
itsLogList->ILogList (records);
}
/** Draw() -- Refreshes the visible portion of the window. **/
void CLogPanorama::Draw
(
Rect *drawRect /* portion of window to refresh */
)
{
short
firstRec, /* record number of first visible line */
hScale, /* how many pixels wide is a character? */
lastRec, /* record number of last line */
totalRec, /* total number of records in LogList */
vScale; /* how many pixels tall is a line? */
register short
currRow, /* window coordinates of current row */
rec; /* loop counter */
char
buff[MAX_LOGREC_CHAR]; /* buffer for fetching log records */
/* First, translate draw rectangle to records. **/
GetScales (&hScale, &vScale);
totalRec = (short)itsLogList->GetNumItems ();
firstRec = (drawRect->top / vScale);
if (firstRec == 0)
firstRec = 1;
lastRec = (drawRect->bottom / vScale) + 1;
if (lastRec > totalRec)
lastRec = totalRec;
/* Refresh all of visible lines. **/
Prepare ();
for (rec=firstRec, currRow=firstRec*vScale;
rec<=lastRec;
rec++, currRow+=vScale)
{
itsLogList->GetString (rec, buff);
MoveTo (LOGPANE_INSET, currRow);
DrawString (CtoPstr(buff));
}
}
/** AddString() -- Adds a new string to panorama. **/
void CLogPanorama::AddString
(
char *theString /* null-terminated string to add */
)
{
Rect
frameRect; /* interior of current frame */
short
listLimits, /* maximum the LogList will hold */
hSpan, /* the horizontal span of frame */
vSpan, /* the vertical span of frame */
hScale, /* horizontal pixels in panarama unit */
vScale; /* vertical pixels in panarama unit */
Point
topRecord, /* LogList record number of top row */
bottomRecord, /* LogList record number of bottom row */
newRecord, /* LogList record number of new row */
currPosition, /* panorama coordinates of top/left frame */
recPosition; /* panorama coordinates of new string */
/* Add the record to the LogList. */
itsLogList->AddString (theString);
/* Get coordinates of current frame and calculate tentative coordinates for
newly added record. */
GetPosition (&currPosition);
GetFrameSpan (&hSpan, &vSpan);
GetScales (&hScale, &vScale);
topRecord.v = currPosition.v + 1;
bottomRecord.v = topRecord.v + vSpan - 1;
newRecord.v = (short)itsLogList->GetNumItems ();
newRecord.h = currPosition.h;
/* Determine where we are in reference to bottom of screen and of list. **/
if (newRecord.v > (bottomRecord.v+1) )
{
/* bottom record isn't visible */
currPosition.v = newRecord.v - vSpan;
ScrollTo (currPosition, FALSE);
GetInterior (&frameRect);
Prepare ();
EraseRect (&frameRect);
}
else
{
/* bottom record is visible */
listLimits = itsLogList->GetMaxRecordCount ();
if (bottomRecord.v < listLimits)
{
/* room in list--create blank line if necessary */
if (newRecord.v == (bottomRecord.v + 1) )
{
Scroll (0, 1, TRUE);
SetRect (&frameRect, newRecord.h*hScale, (newRecord.v-1)*vScale,(newRecord.h+hSpan)*hScale, (newRecord.v)*vScale);
}
else
SetRect (&frameRect, newRecord.h*hScale, (newRecord.v-1)*vScale,
(newRecord.h+hSpan-1)*hScale, (newRecord.v)*vScale);
}
else if (bottomRecord.v > listLimits)
{
currPosition.v = newRecord.v - vSpan;
ScrollTo (currPosition, FALSE);
GetInterior (&frameRect);
Prepare ();
EraseRect (&frameRect);
}
else
{
/* bottom of pane=limit of list, so do our own scrolling */
Prepare ();
GetInterior (&frameRect);
ScrollRect (&frameRect, 0, -vScale, gUtilRgn);
SetRect (&frameRect, bottomRecord.h*hScale, (bottomRecord.v-1)*vScale,(bottomRecord.h+hSpan-1)*hScale, (bottomRecord.v)*vScale);
EraseRect (&frameRect);
}
}
Draw (&frameRect);
itsScrollPane->Calibrate();
}